using StackExchange.Redis;
using System.Text.Json;

namespace Traceability.API.Services
{
    /// <summary>
    /// Redis缓存服务
    /// </summary>
    public class RedisService
    {
        private readonly ConnectionMultiplexer _redis;
        private readonly IDatabase _db;
        private readonly IConfiguration _configuration;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="configuration">配置</param>
        public RedisService(IConfiguration configuration)
        {
            _configuration = configuration;
            
            // 从配置中读取Redis连接信息
            var redisConfig = new ConfigurationOptions
            {
                EndPoints = { { _configuration["Redis:Host"], int.Parse(_configuration["Redis:Port"]) } },
                Password = _configuration["Redis:Password"],
                ConnectTimeout = int.Parse(_configuration["Redis:ConnectTimeout"]),
                SyncTimeout = int.Parse(_configuration["Redis:ResponseTimeout"]),
                AbortOnConnectFail = false,
                AllowAdmin = true
            };

            _redis = ConnectionMultiplexer.Connect(redisConfig);
            _db = _redis.GetDatabase(int.Parse(_configuration["Redis:Database"]));
        }

        /// <summary>
        /// 设置字符串值
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <param name="expiry">过期时间（秒）</param>
        /// <returns>是否成功</returns>
        public async Task<bool> StringSetAsync(string key, string value, int expiry = -1)
        {
            return await _db.StringSetAsync(key, value, expiry > 0 ? TimeSpan.FromSeconds(expiry) : null);
        }

        /// <summary>
        /// 获取字符串值
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>值</returns>
        public async Task<string> StringGetAsync(string key)
        {
            return await _db.StringGetAsync(key);
        }

        /// <summary>
        /// 设置对象
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <param name="expiry">过期时间（秒）</param>
        /// <returns>是否成功</returns>
        public async Task<bool> SetAsync<T>(string key, T value, int expiry = -1) where T : class
        {
            var json = JsonSerializer.Serialize(value);
            return await StringSetAsync(key, json, expiry);
        }

        /// <summary>
        /// 获取对象
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="key">键</param>
        /// <returns>对象</returns>
        public async Task<T> GetAsync<T>(string key) where T : class
        {
            var value = await StringGetAsync(key);
            if (string.IsNullOrEmpty(value))
            {
                return null;
            }
            return JsonSerializer.Deserialize<T>(value);
        }

        /// <summary>
        /// 删除键
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>是否成功</returns>
        public async Task<bool> DeleteAsync(string key)
        {
            return await _db.KeyDeleteAsync(key);
        }

        /// <summary>
        /// 判断键是否存在
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>是否存在</returns>
        public async Task<bool> ExistsAsync(string key)
        {
            return await _db.KeyExistsAsync(key);
        }

        /// <summary>
        /// 设置过期时间
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="expiry">过期时间（秒）</param>
        /// <returns>是否成功</returns>
        public async Task<bool> ExpireAsync(string key, int expiry)
        {
            return await _db.KeyExpireAsync(key, TimeSpan.FromSeconds(expiry));
        }

        /// <summary>
        /// 哈希表设置字段
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="field">字段</param>
        /// <param name="value">值</param>
        /// <returns>是否成功</returns>
        public async Task<bool> HashSetAsync(string key, string field, string value)
        {
            return await _db.HashSetAsync(key, field, value);
        }

        /// <summary>
        /// 哈希表获取字段
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="field">字段</param>
        /// <returns>值</returns>
        public async Task<string> HashGetAsync(string key, string field)
        {
            return await _db.HashGetAsync(key, field);
        }

        /// <summary>
        /// 哈希表删除字段
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="field">字段</param>
        /// <returns>是否成功</returns>
        public async Task<bool> HashDeleteAsync(string key, string field)
        {
            return await _db.HashDeleteAsync(key, field);
        }

        /// <summary>
        /// 哈希表判断字段是否存在
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="field">字段</param>
        /// <returns>是否存在</returns>
        public async Task<bool> HashExistsAsync(string key, string field)
        {
            return await _db.HashExistsAsync(key, field);
        }

        /// <summary>
        /// 获取所有哈希字段和值
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>字段和值的字典</returns>
        public async Task<Dictionary<string, string>> HashGetAllAsync(string key)
        {
            var hashEntries = await _db.HashGetAllAsync(key);
            return hashEntries.ToDictionary(
                he => he.Name.ToString(),
                he => he.Value.ToString());
        }

        /// <summary>
        /// 列表左侧插入
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <returns>列表长度</returns>
        public async Task<long> ListLeftPushAsync(string key, string value)
        {
            return await _db.ListLeftPushAsync(key, value);
        }

        /// <summary>
        /// 列表右侧插入
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <returns>列表长度</returns>
        public async Task<long> ListRightPushAsync(string key, string value)
        {
            return await _db.ListRightPushAsync(key, value);
        }

        /// <summary>
        /// 列表左侧弹出
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>值</returns>
        public async Task<string> ListLeftPopAsync(string key)
        {
            return await _db.ListLeftPopAsync(key);
        }

        /// <summary>
        /// 列表右侧弹出
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>值</returns>
        public async Task<string> ListRightPopAsync(string key)
        {
            return await _db.ListRightPopAsync(key);
        }

        /// <summary>
        /// 获取列表范围
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="start">开始位置</param>
        /// <param name="stop">结束位置</param>
        /// <returns>值列表</returns>
        public async Task<List<string>> ListRangeAsync(string key, long start = 0, long stop = -1)
        {
            var values = await _db.ListRangeAsync(key, start, stop);
            return values.Select(v => v.ToString()).ToList();
        }

        /// <summary>
        /// 获取列表长度
        /// </summary>
        /// <param name="key">键</param>
        /// <returns>列表长度</returns>
        public async Task<long> ListLengthAsync(string key)
        {
            return await _db.ListLengthAsync(key);
        }

        /// <summary>
        /// 设置位图位置的值
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="offset">位置</param>
        /// <param name="value">值</param>
        /// <returns>是否成功</returns>
        public async Task<bool> SetBitAsync(string key, long offset, bool value)
        {
            return await _db.StringSetBitAsync(key, offset, value);
        }

        /// <summary>
        /// 获取位图位置的值
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="offset">位置</param>
        /// <returns>值</returns>
        public async Task<bool> GetBitAsync(string key, long offset)
        {
            return await _db.StringGetBitAsync(key, offset);
        }
    }
} 